Skip to content

Fix several ScrollConsoleScreenBuffer ConPTY issues - #20774

Merged
Leonard Hecker (lhecker) merged 3 commits into
mainfrom
dev/lhecker/20772-deccra-fixes
Oct 7, 2026
Merged

Leonard Hecker (lhecker) merged 3 commits into
mainfrom
dev/lhecker/20772-deccra-fixes

Conversation

@lhecker

@lhecker Leonard Hecker (lhecker) commented Oct 6, 2026 •

Copy link
Copy Markdown
Member

Also closes MSFT-64450466.

As a drive-by:

  • Fixed the DECCRA path not restoring cursor attributes in conhost.
  • Reduced memory use in the non-DECCRA path.
  • Added a IL/DL sequence fast-pass for ScrollConsoleScreenBuffer.
  • Fixed a broken bounds checks in Read/WriteConsoleOutputWImplHelper.
  • Fixed the TraceLogging definition for SMALL_RECT.

Comment thread src/host/ut_host/VtIoTests.cpp Fixed
@github-actions

This comment has been minimized.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this seems right to me, thanks for like seven bug fixes :D

Comment thread src/host/getset.cpp Outdated
Comment on lines +1027 to +1028
// Several applications scroll the entire screen vertically with a whitespace fill, to essentially replicate
// what SU/SD can do. Our VT application is faster and better, so let's use that whenever applicable.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

James Holderness (@j4james) does this seem reasonable to you? Win32 API ScrollConsole with a full-screen rectangle, moved only vertically, with no non-color attributes, being translated into SU or SD?

(My only question is what color it's filled with when we do this vs the console API?)

Comment thread src/host/getset.cpp Outdated
Comment on lines +1027 to +1028
// Several applications scroll the entire screen vertically with a whitespace fill, to essentially replicate
// what SU/SD can do. Our VT application is faster and better, so let's use that whenever applicable.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally I'd prefer we didn't use SU and SD for this, because this is not the standard way these operations are supposed to work, so the behavior is not reliable. The correct way to scroll buffer contents like this would be with DL and IL sequences, although the downside is that you'd need to home the cursor first.

@lhecker Leonard Hecker (lhecker) Oct 6, 2026 •

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In what way SU/SD are not reliable in this context?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(I cleared my approval to allow for the discussion - thx!)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SU and SD are officially panning operations, for use when you have a page size that is larger than your visible window (see the VT510 documentation for SU and SD). When the page size is the same as the visible window they do nothing.

In addition to that, terminals that follow an Xterm-like interpretation of SU and SD don't all implement it the same way. Some (like Windows Terminal) will delete the top row when scrolling the full window up with SU. Others (like Xterm) will move the top row into the backscroll buffer.

And then of course there are terminals that don't implement SU or SD at all, simply because they're not a conformance requirement (they're defined as part of the windowing extension, so if you don't support windowing you wouldn't expect to implement them).

IL and DL are a level 1 conformance requirement, though, so they're much more likely to be supported consistently by modern terminals. Although if you want to be ultra-conservative, it's worth noting that they weren't implemented on the original VT100 range (they were only made a level 1 requirement later), so there may still be some strict VT100 emulators that won't support them either.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright, I hope this is correct. A big chunk of code moved upward in there so I can early-return on empty scroll rects. I used DECSC/DECRC again to implement cursor and attribute restore, which... I guess is fine considering how much we (I?) came to rely on it.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It just occurred to me that this IL/DL approach might have another little problem. If the cursor is visible at the time of the operation, it's possible the user will see it jumping to the home position and back again whenever a scroll operation occurs. Do we perhaps also need to hide and restore the cursor here?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm alright with that in this case as we have other places in this flow where we save/restore the cursor and let it potentially flicker a little bit; if we tackle it for IL/DL we can do it all at once for the other ones too :)

Comment thread src/host/getset.cpp
{
const auto clipViewport = clip ? Viewport::FromInclusive(*clip).Clamp(bufferSize) : bufferSize;
const auto sourceViewport = Viewport::FromInclusive(source);
const auto fillViewport = sourceViewport.Clamp(clipViewport);

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This diff is certainly a lot easier to read with

git diff --diff-algorithm=histogram --color-moved=dimmed-zebra --color-moved-ws=allow-indentation-change main..dev/lhecker/20772-deccra-fixes

@DHowett

Copy link
Copy Markdown
Member

L, I fixed the PR body to not mention SU/SD

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I gave this a quick test in Terminal, PuTTY and WezTerm and am fairly comfortable with it. Thank you. and thank you James for us not stumbling into SU being ~ ~ unreliable ~ ~

@lhecker
Leonard Hecker (lhecker) merged commit 5951f69 into main Oct 7, 2026
20 checks passed
@lhecker
Leonard Hecker (lhecker) deleted the dev/lhecker/20772-deccra-fixes branch October 7, 2026 23:17
@DHowett Dustin L. Howett (DHowett) moved this from To Cherry Pick to Cherry Picked in 1.25 Servicing Pipeline Oct 26, 2026
Dustin L. Howett (DHowett) pushed a commit that referenced this pull request Oct 26, 2026
- Fixed #20772 by fully committing to lazy DA1 capabilities path via
  `VtIo::SetDeviceAttributes`. It accidentally only did so with enabled
  cursor inheritance before.
- Fixed #20773 by fixing the source/destination rectangle alignment
  in the non-DECCRA path of `ScrollConsoleScreenBuffer`.

Also closes MSFT-64450466.

As a drive-by:
- Fixed the DECCRA path not restoring cursor attributes in conhost.
- Reduced memory use in the non-DECCRA path.
- Added a `IL/DL` sequence fast-pass for `ScrollConsoleScreenBuffer`.
- Fixed a broken bounds checks in `Read/WriteConsoleOutputWImplHelper`.
- Fixed the TraceLogging definition for `SMALL_RECT`.

(cherry picked from commit 5951f69)
Service-Card-Id: PVTI_lADOAF3p4s4BlIihzg--Oqg PVTI_lADOAF3p4s4BlIihzg--OrY
Service-Version: 1.26
Dustin L. Howett (DHowett) pushed a commit that referenced this pull request Oct 26, 2026
- Fixed #20772 by fully committing to lazy DA1 capabilities path via
  `VtIo::SetDeviceAttributes`. It accidentally only did so with enabled
  cursor inheritance before.
- Fixed #20773 by fixing the source/destination rectangle alignment
  in the non-DECCRA path of `ScrollConsoleScreenBuffer`.

Also closes MSFT-64450466.

As a drive-by:
- Fixed the DECCRA path not restoring cursor attributes in conhost.
- Reduced memory use in the non-DECCRA path.
- Added a `IL/DL` sequence fast-pass for `ScrollConsoleScreenBuffer`.
- Fixed a broken bounds checks in `Read/WriteConsoleOutputWImplHelper`.
- Fixed the TraceLogging definition for `SMALL_RECT`.

(cherry picked from commit 5951f69)
Service-Card-Id: PVTI_lADOAF3p4s4BQX0-zg--Omw PVTI_lADOAF3p4s4BQX0-zg--Op8 PVTI_lADOAF3p4s4BQX0-zg-_abM
Service-Version: 1.25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Cherry Picked
Status: To Cherry Pick

Development

Successfully merging this pull request may close these issues.

ConPTY: Non-DECCRA/DECFRA scrolling produces incorrect results 1.25+: ConPTY ignores DA1 response

4 participants